import yaml
import traceback

from driver import Driver
from activity import Activity
from util import load_actions
from logger import logger
from actions.activity.start_activity_action import StartActivityAction
from actions.activity.init_activity_element_action import InitActivityElementAction


class Crawler:

    def __init__(self):
        self.config = yaml.load(open("config.yml", encoding="utf-8"))
        self.driver = Driver(self.config)
        actions = self.config.get("actions")

        Activity.driver = self.driver

        self.init_actions = load_actions(actions.get("init", []))
        self.actions = load_actions(actions.get("run", []))
        self.tearDown_actions = load_actions(actions.get("tearDown", []))
        self.activity_actions = [
            StartActivityAction(),
            InitActivityElementAction()
        ]
        self.activity = None

    def load_activity(self, activity):
        key = activity.key()
        if key not in Activity.activities:
            Activity.activities[key] = activity
        for el, ac in activity.next:
            self.load_activity(ac)

    def crawler(self):
        self.init()

        try:
            while self.run():
                pass
        except Exception as e:
            logger.error(e)
            traceback.print_exc()

        logger.info(" ==== crawler end ==== ")
        self.tear_down()

    def tear_down(self):
        logger.info(" ==== tearDown ==== ")
        if self.activity is None:
            return

        head = self.activity.get_head()
        for action in self.tearDown_actions:
            action.entrance(head, self.config, self.driver)

    def init(self):
        for action in self.init_actions:
            action.init(self)

    def run(self):
        if not self._do_activity_action():
            return False

        logger.info("activity: {}".format(self.activity))
        logger.info("next activity：{}".format(self.activity.next))

        if self.activity.element is None:
            if not self._do_run_actions():
                return False

        if not self._do_element_action():
            return False

        return True

    def _do_run_actions(self):
        for action in self.actions:
            if not action.entrance(self.activity, self.config, self.driver):
                break

        return True

    def _do_activity_action(self):
        for action in self.activity_actions:
            self.activity = action.entrance(self.activity, self.config, self.driver)
        return True

    def _do_element_action(self):
        if self.activity.element is not None:
            if self.activity.action == "send_key":
                self.driver.send_key(self.activity.element, self.activity.args)
            if self.activity.action == "click":
                self.driver.click(self.activity.element)
        else:
            self.driver.back()
        return True


if __name__ == '__main__':
    pass
